package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.activity.util.DateUtil;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.redisson.misc.Hash;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

/**
 * @author mqx
 * @date 2020-10-28 09:19:38
 */
@Component
public class SeckillReceiver {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    //  开启消息的监听
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_1}
    ))
    public void importItemToRedis(Message message, Channel channel){
        //  数据初始化！  需要将秒杀的商品放入缓存！
        //  先将数据从数据库中查询出来！必须有条件！
        //  审核状态status=1 表示审核通过！    start_time = new Date();    库存数>0;
        QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
        seckillGoodsQueryWrapper.eq("status","1");
        seckillGoodsQueryWrapper.eq("DATE_FORMAT(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
        seckillGoodsQueryWrapper.gt("stock_count",0);
        List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
        //  获取到秒杀的商品集合
        if(!CollectionUtils.isEmpty(seckillGoodsList)){
            //  需要将秒杀的商品放入缓存！
            //  SeckillGoods 采用hash 数据类型！
            //  redisTemplate.boundHashOps();
            //  redisTemplate.opsForHash()
            //  hash  hset (key,field,value);
            //  Hash key = RedisConst.SECKILL_GOODS  seckill:goods ,field=skuId,value=SeckillGoods
            //  循环秒杀商品，将数据放入缓存

            for (SeckillGoods seckillGoods : seckillGoodsList) {
                //  判断当前缓存中是否有该商品！
                Boolean flag = redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).hasKey(seckillGoods.getSkuId().toString());
//                Boolean aBoolean1 = redisTemplate.opsForHash().hasKey(RedisConst.SECKILL_GOODS, seckillGoods.getSkuId().toString());
                //  表示缓存中有当前的秒杀商品！
                if (flag){
                    continue;
                }
                //  表示缓存中没有当的秒杀商品
                redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).put(seckillGoods.getSkuId().toString(),seckillGoods);
                //  如何防止库存超卖的?  使用redis -- list 数据类型！
                //  key = seckill:stock:29   value = skuId  seckillGoods.getSkuId().toString()
                //  RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId()
                //  这样写，只放入了一次！ 应该有多个商品数，循环多少次！
                for (Integer i = 0; i < seckillGoods.getNum(); i++) {
                    redisTemplate.opsForList().leftPush(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId(),seckillGoods.getSkuId().toString());
                    //redisTemplate.opsForList().leftPush(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId(),seckillGoods.getSkuId().toString(),);
                }

                //  每个秒杀商品在初始化的时候，那么都是 1 {seckillpush  seckillGoods.getSkuId()+":1"}
                redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");

            }
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }


    //  监听操作
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = {MqConst.ROUTING_SECKILL_USER}
    ))
    public void seckill(UserRecode userRecode,Message message ,Channel channel){
        //  判断数据是否为空
        if (userRecode!=null){
            //  调用一个方法。
            seckillGoodsService.seckillOrder(userRecode.getSkuId(), userRecode.getUserId());
        }

        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //  监听清空缓存数据
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_18,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_18}
    ))
    public void clearRedis(Message message,Channel channel){
        //  秒杀结束之后的数据！
        //  秒杀结束时间等于系统时间，同时状态1
        QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
        seckillGoodsQueryWrapper.eq("status","1");
        seckillGoodsQueryWrapper.eq("DATE_FORMAT(end_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
        List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
        //  循环遍历 hash  key = seckill:goods field = skuId
        if (!CollectionUtils.isEmpty(seckillGoodsList)){
            for (SeckillGoods seckillGoods : seckillGoodsList) {
                //  RedisConst.SECKILL_STOCK_PREFIX + seckillGoods.getSkuId()
                //  删除库存！ key =  seckill:goods  field = skuId
                //  redisTemplate.boundHashOps(RedisConst.SECKILL_GOODS).delete(seckillGoods.getSkuId());

                //  删除秒杀的库存数量
                redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId());
            }
        }
        //  商品所有的秒杀商品：key =  seckill:goods
        redisTemplate.delete(RedisConst.SECKILL_GOODS);
        //  删除订单数据
        redisTemplate.delete(RedisConst.SECKILL_ORDERS_USERS);
        //  删除如果用户只抢购成功，但是，没有下订单，将预下单删除
        redisTemplate.delete(RedisConst.SECKILL_ORDERS);

        //  将数据库中的数据更新成非秒杀状态,更新状态 status = 2
        SeckillGoods seckillGoods = new SeckillGoods();
        seckillGoods.setStatus("2");
        seckillGoodsMapper.update(seckillGoods,seckillGoodsQueryWrapper);

        // 确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}
